﻿using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using Nexus.IPConfiguration.Management.Wrappers;

namespace Nexus.IPConfiguration.Management
{
    /// <summary>
    /// Handles windows proxy management
    /// </summary>
    public class SystemProxyManagement
    {
        #region properties
        /// <summary>
        /// Indicates if proxy is enabled on this system
        /// </summary>
        public static bool IsProxyEnabled
        {
            get
            {
                using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", false))
                {
                    return (int)key.GetValue("ProxyEnable") == 1;
                }
            }
        }
        #endregion

        #region constants
        private static readonly int INTERNET_OPTION_SETTINGS_CHANGED = 39;
        private static readonly int INTERNET_OPTION_REFRESH = 37;
        #endregion

        #region static methods
        /// <summary>
        /// Disables proxy
        /// </summary>
        public static void DisableProxy()
        {
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true))
            {
                key.SetValue("ProxyEnable", 0);
            }

            bool settingReturn;
            bool refreshReturn;

            settingReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
            refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
        }

        /// <summary>
        /// Enables proxy
        /// </summary>
        /// <param name="proxy">Proxy server address</param>
        /// <param name="port">Proxy server port</param>
        /// <param name="proxyOverride">Proxy override</param>
        public static void EnableProxy(string proxy, int port, string proxyOverride)
        {
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true))
            {
                key.SetValue("ProxyServer", string.Format("{0}:{1}", proxy, port));
                key.SetValue("ProxyOverride", proxyOverride);
                key.SetValue("ProxyEnable", 1);
            }

            bool settingsReturn;
            bool refreshReturn;

            settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
            refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
        }

        /// <summary>
        /// Enables proxy
        /// </summary>
        /// <param name="proxyConfig">Proxy configuration</param>
        public static void EnableProxy(ProxyConfig proxyConfig)
        {
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", true))
            {
                key.SetValue("ProxyServer", string.Format("{0}:{1}", proxyConfig.ProxyAddress, proxyConfig.Port));
                key.SetValue("ProxyOverride", proxyConfig.ProxyOverride);
                key.SetValue("ProxyEnable", 1);
            }

            bool settingsReturn;
            bool refreshReturn;

            settingsReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_SETTINGS_CHANGED, IntPtr.Zero, 0);
            refreshReturn = InternetSetOption(IntPtr.Zero, INTERNET_OPTION_REFRESH, IntPtr.Zero, 0);
        }

        /// <summary>
        /// Gets information about current proxy config
        /// </summary>
        /// <returns>ProxyConfig instance if proxy is enabled in system, null otherwise</returns>
        public static ProxyConfig GetCurrentProxyConfig()
        {
            ProxyConfig config = new ProxyConfig();
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings", false))
            {
                if ((int)key.GetValue("ProxyEnable") == 1)
                {
                    string proxy = key.GetValue("ProxyServer") as string;
                    var parts = proxy.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                    config.Port = int.Parse(parts[1]);
                    config.ProxyAddress = parts[0];
                    config.ProxyOverride = key.GetValue("ProxyOverride") as string;
                }
                else
                {
                    config = null;
                }
            }
            return config;
        }
        #endregion

        #region imported methods
        [DllImport("wininet.dll")]
        private static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength);
        #endregion
    }
}
